/**
	Copyright (c) 2010 ATTi 
	All rights reserved.
	Author: Michael Shu
	Date: 1/22/2010
*/

@isTest

private class CaseCreateAndRollUpSummaryTriggerTester {
	private static String ACCOUNTMODE = 'Account';
	private static String INCIDENTMODE = 'Incident';
	private static String STUBMODE = 'Stub';
	private static String CRFMODE = 'CRF';
	private static String CRFMODE_WEST = 'CRF WEST';
	private static ID IOGIncident_CASE_RecordType = RecordTypeHelper.GetRecordTypeID('Case', 'IOG Incident'); 
	private static ID IOGChangeTask_CASE_RecordType = RecordTypeHelper.GetRecordTypeID('Case', 'IOG Change Task'); 
	private static ID IOGInquiry_CASE_RecordType = RecordTypeHelper.GetRecordTypeID('Case', 'IOG Inquiry');
    private static ID IOGContentTask_CASE_RecordType = RecordTypeHelper.GetRecordTypeID('Case', 'IOG Content Task');
	
	private static String  EASTROLE = 'IOG EAST - Support L1 - Supervisor';
	private static String  WESTROLE = 'IOG WEST - Support L1 - Manager';
	private static String   OORROLE = 'IOG OOR - Support L2 - Rep';
	private static String ADMINROLE = 'Information Systems';
	
	private static String  EASTPROFILE = 'IOG Support - Standard - East';
	private static String  WESTPROFILE = 'IOG Support - Standard - West';
	private static String   OORPROFILE = 'IOG Support - Standard - OOR';	 
	private static String ADMINPROFILE = 'System Administrator';
	
	private static User EastUser;
	private static User WestUser;
	private static User OORUser;
	private static User sysUser;
	private static ID EASTAcctId;
	private static ID WESTAcctId;
	private static ID OORAcctId;
	
	private static ID EASTContactId;
	private static ID WESTContactId;
	private static ID OORContactId;
	
	private static void initialize(){
		addUsers();
		addAccountContacts();
	}
	
	private static User getUser(String name, ID profileId, ID roleId){
	    User u = new User();
		u.UserName = 'test' + name + '@atti-temp.com';
		u.LastName = 'test' + name;
		u.ATTUID__c = name;
		u.Email = 'null@att-temp.com';
		u.Alias = 'test';
		u.CommunityNickname = name;
		u.ProfileId = profileId;
		u.UserRoleId = roleId;
		u.LanguageLocaleKey = 'en_US';
		u.TimeZoneSidKey = 'America/Los_Angeles';
		u.LocaleSidKey = 'en_US';
		u.EmailEncodingKey = 'UTF-8';
		return u;		
	}

	private static void addUsers(){
		Set<String> profileNames = new Set<String>{EASTPROFILE, WESTPROFILE, OORPROFILE ,ADMINPROFILE};
		Set<String> roleNames = new Set<String>{EASTROLE, WESTROLE, OORROLE, ADMINROLE};
		List<Profile> profiles = [select ID, Name from Profile where Name IN: profileNames];
		List<UserRole> roles = [select ID, Name from UserRole where Name IN: roleNames];
		Map<String, ID> profileMap = new Map<String, ID>();
		Map<String, ID> rolesMap = new Map<String, ID>();
		for(Profile p : profiles){
			profileMap.put(p.Name, p.Id);
		}
		for(UserRole r : roles){
			rolesMap.put(r.Name, r.Id);
		}
		sysUser  = getUser('sysUser',  profileMap.get(ADMINPROFILE), rolesMap.get(ADMINROLE));
		EastUser = getUser('eastUser', profileMap.get(EASTPROFILE),  rolesMap.get(EASTROLE));
		WestUser = getUser('westUser', profileMap.get(WESTPROFILE),  rolesMap.get(WESTROLE));
		OORUser  = getUser('oorUser',  profileMap.get(OORPROFILE),   rolesMap.get(OORROLE));
		List<User> users = new List<User>{sysUser, EastUser, WestUser, OORUser};
		insert(users);
	}
	
	private static void addAccountContacts(){			
		Account eastAcct = new Account();
		eastAcct.RecordTypeId = RecordTypeHelper.GetRecordTypeIdByDevName('Account', 'CSS_Customer');
		eastAcct.Name = 'test East Account';	
		eastAcct.CSS_CustomerRegionCode__c = 'southeast';
		eastAcct.OwnerId = EastUser.Id;
		eastAcct.CSS_CustomerID__c = 'eeeeeeeeee'; 

		Account westAcct = new Account();
		westAcct.RecordTypeId = RecordTypeHelper.GetRecordTypeIdByDevName('Account', 'CSS_Customer');
		westAcct.Name = 'test East Account';	
		westAcct.CSS_CustomerRegionCode__c = 'west';
		westAcct.OwnerId = WestUser.Id;
		westAcct.CSS_CustomerID__c = 'wwwwwwwwww';

		Account oorAcct = new Account();
		oorAcct.RecordTypeId = RecordTypeHelper.GetRecordTypeIdByDevName('Account', 'Local_Advertiser');
		oorAcct.Name = 'test OOR Account';
		oorAcct.OwnerId = OORUser.Id;
		oorAcct.AFrontier_CustomerID__c = 'oooooooooo';
		
		List<Account> accounts = new List<Account>{eastAcct, westAcct, oorAcct};				
		System.runAs(sysUser){
		    insert accounts;
		}
		EASTAcctId = eastAcct.Id;
		WESTAcctId = westAcct.Id;
		OORAcctId = oorAcct.Id;		

		Contact eastCont = new Contact();
		eastCont.AccountId = EASTAcctId;
		eastCont.OwnerId = EastUser.Id;
		eastCont.LastName = 'test east Contact';
		eastCont.Email = 'test@att-temp.com';
		eastCont.RecordTypeId = RecordTypeHelper.GetRecordTypeIdByDevName('Contact', 'CSS_Contact');

		Contact westCont = new Contact();
		westCont.AccountId = WESTAcctId;
		westCont.OwnerId = WestUser.Id;
		westCont.LastName = 'test west Contact';
		westCont.Email = 'test@att-temp.com';
		westCont.RecordTypeId = RecordTypeHelper.GetRecordTypeIdByDevName('Contact', 'CSS_Contact');
		
		Contact oorCont = new Contact();
		oorCont.AccountId = OORAcctId;
		oorCont.OwnerId = OORUser.Id;
		oorCont.LastName = 'test oor Contact';
		oorCont.Email = 'test@att-temp.com';
		oorCont.RecordTypeId = RecordTypeHelper.GetRecordTypeIdByDevName('Contact', 'CSS_Contact');		
		List<Contact> contacts = new List<Contact>{eastCont, westCont, oorCont};
			
		System.runAs(sysUser){
			insert contacts;
		}
		EASTContactId = eastCont.Id;
		WESTContactId = westCont.Id;
		OORContactId = oorCont.Id;	
	}
	
	private static Case createNewIncidentCaseWithPackageFields(String origin, String mode, String CRFrequestType, User usr, ID acctid, ID contid){
		Case cs = new Case();
		cs.Subject = 'any Subject';
		cs.Description = 'any Description';
		cs.Origin = origin;
		cs.Status = 'Open';
		cs.AccountId = acctid;
		cs.ContactId = contid;
		cs.OwnerId = usr.Id;
		cs.RecordTypeId = IOGIncident_CASE_RecordType;
		String[] ss = getCRFPackageAndCRFrequestTypeValue(mode, CRFrequestType);
		cs.CRF_PACKAGE__c = ss[0];
		cs.CRF_Request_Type__c = ss[1];
		if(origin == 'Email' || origin == 'CRF'){
			System.runAs(sysUser){
				insert cs;
			}
		}else{
			System.runAs(usr){
				insert cs;
			}
		}
		return cs;
	}

	private static Case createNewIncidentCaseOnlyNoPackageFields(String origin, User usr, ID acctid, ID contid){
		Case cs = new Case();
		cs.Subject = 'any Subject';
		cs.Description = 'any Description';
		cs.Origin = origin;
		cs.Status = 'Open';
		cs.AccountId = acctid;
		cs.ContactId = contid;
		cs.OwnerId = usr.Id;
		cs.RecordTypeId = IOGIncident_CASE_RecordType;
		if(origin == 'Email' || origin == 'CRF'){
			System.runAs(sysUser){
				insert cs;
			}
		}else{
			System.runAs(usr){
				insert cs;
			}
		}
		return cs;
	}

	private static Case createNewStubCaseManually(Case p, User usr, ID stubRecordTypeId, String productFamily){
		Case cs = new Case();
		cs.ParentId = p.Id;
		cs.RecordTypeId = stubRecordTypeId;
		cs.Product_Family__c = productFamily;
		System.runAs(usr){
			insert cs;
		}
		return cs;
	}
			
	private static String[] getCRFPackageAndCRFrequestTypeValue(String mode, String CRFrequestType){
		String[] rst = new String[9];
		if(mode == INCIDENTMODE){
			rst[1]  = null;
			rst[0]  = 'IOG Change Task<col>loda 1.0<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code1<col>UDAC Description <row>';
			rst[0] += 'IOG Change Task<col>mobile website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code2<col>UDAC Description <row>';
			rst[0] += 'IOG Change Task<col>basic video<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code3<col>UDAC Description <row>';
			rst[0] += 'IOG Change Task<col>self-submit video<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code4<col>UDAC Description <row>';
			rst[0] += 'IOG Change Task<col>premium website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code5<col>UDAC Description <row>';
		}else if(mode == ACCOUNTMODE){
			rst[1]  = (CRFrequestType == null)? 'Change Request - Update Information' : CRFrequestType;
			rst[0]  = '<col>loda 1.0<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code6<col>UDAC Description <row>';
			rst[0] += '<col>mobile website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code7<col>UDAC Description <row>';
			rst[0] += '<col>basic video<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code8<col>UDAC Description <row>';
			rst[0] += '<col>self-submit video<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code9<col>UDAC Description <row>';
			rst[0] += '<col>premium website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code10<col>UDAC Description <row>';
		}else if(mode == STUBMODE){
			rst[1]  = null;
			rst[0]  = '<col>loda 1.0<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code11<col>UDAC Description ';
		}else if(mode == CRFMODE){
			rst[1]  = (CRFrequestType == null)? 'Change Request - Update Information' : CRFrequestType;
			rst[0]  = '<col>basic video<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code6<col>UDAC Description <row>';
			rst[0] += '<col>loda 1.0<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code7<col>UDAC Description <row>';
			rst[0] += '<col>mobile website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code8<col>UDAC Description <row>';
			rst[0] += '<col>premium website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code9<col>UDAC Description <row>';
			rst[0] += '<col>self-submit video<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code10<col>UDAC Description <row>';
			rst[3]  = 'IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support;' 
			        + 'IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support';   // east region & standard 
			rst[4]  = 'IOG IR - Sales Escalation;IOG IR - Sales Escalation;IOG IR - Sales Escalation;'
			        + 'IOG IR - Sales Escalation;IOG IR - Sales Escalation;IOG IR - Sales Escalation';                           // east region & escalated 
			rst[5]  = 'IOG WEST - Sales & Customer Support;IOG WEST - Sales & Customer Support;IOG IR - Sales & Customer Support;' 
			        + 'IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support;IOG WEST - Sales & Customer Support'; // west region & standard
			rst[6]  = 'IOG WEST - Sales Escalation;IOG WEST - Sales Escalation;IOG WEST - Sales Escalation;' 
			        + 'IOG WEST - Sales Escalation;IOG WEST - Sales Escalation;IOG WEST - Sales Escalation';                     // west region & escalated
			rst[7]  = 'IOG OOR - Sales & Customer Support;IOG OOR - Sales & Customer Support;IOG OOR - Sales & Customer Support;' 
			        + 'IOG OOR - Sales & Customer Support;IOG OOR - Sales & Customer Support;IOG OOR - Sales & Customer Support';// oor region & standard
			rst[8]  = 'IOG OOR - Sales Escalation;IOG OOR - Sales Escalation;IOG OOR - Sales Escalation;' 
			        + 'IOG OOR - Sales Escalation;IOG OOR - Sales Escalation;IOG OOR - Sales Escalation';                        // oor region & escalated
		}else if(mode == CRFMODE_WEST){
			rst[1]  = (CRFrequestType == null)? 'Change Request - Update Information' : CRFrequestType;
			rst[0]  = '<col>yp360<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code6<col>UDAC Description <row>';
			rst[0] += '<col>loda 1.0<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code7<col>UDAC Description <row>';
			rst[0] += '<col>mobile website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code8<col>UDAC Description <row>';
			rst[0] += '<col>premium website<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code9<col>UDAC Description <row>';
			rst[0] += '<col>pay per call<col>Feature Code<col>209<col>109<col>O<col><col>Product Issue<col>Product/Directory Code<col>UDAC Code10<col>UDAC Description <row>';
			rst[5]  = 'IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support;' 
			        + 'IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support;IOG IR - Sales & Customer Support'; // west region & standard
			rst[6]  = 'IOG IR - Sales Escalation;IOG IR - Sales Escalation;IOG IR - Sales Escalation;'                   
			        + 'IOG IR - Sales Escalation;IOG IR - Sales Escalation;IOG IR - Sales Escalation'; 	                       // west region & escalated
		}else{
			rst[0]  = null;
		}
		return rst;
	}
	
	private static void addNewFulfillmentItemRecordsForInitiateChange(Case c){
		Fulfillment_Product_Group__c fulprodgroup = new Fulfillment_Product_Group__c();
		fulprodgroup.Name = c.Fulfillment_Product_Group_Name__c;
		System.runAs(SysUser){
			insert fulprodgroup;
		}
		
		Fulfillment_Products__c fulprods = new Fulfillment_Products__c();
		fulprods.Fulfillment_Product_Group__c = fulprodgroup.Id;
		fulprods.Product_UDAC_Code__c = c.UDAC_Code__c;
		fulprods.Status__c = 'Active';
		System.runAs(SysUser){
			insert fulprods;
		}
						
		Workflow_Definition__c wf_def = new Workflow_Definition__c();
		wf_def.Name = c.Fulfillment_Product_Group_Name__c;
		wf_def.Status__c = 'Active';
		System.runAs(SysUser){
			insert wf_def;
		}

		Workflow_Fulfillment_Group__c wf_fulgroup = new Workflow_Fulfillment_Group__c();
		wf_fulgroup.Order_Types__c = 'Change Request';
		wf_fulgroup.status__c ='Active';
		wf_fulgroup.Product_Group__c = fulprodgroup.Id;
		wf_fulgroup.Advertiser_Region__c = c.Region__c;
		wf_fulgroup.Workflow__c = wf_def.Id;
		System.runAs(SysUser){
			insert wf_fulgroup;
		}
				
		Stage_Definition__c function_pre_definition = new Stage_Definition__c();
		function_pre_definition.Name = 'Verification';
		function_pre_definition.Status__c = '';
		function_pre_definition.Sequence__c = 78;
		System.runAs(SysUser){
			insert function_pre_definition;
		}		
		
		Workflow_Stage__c wf_function = new Workflow_Stage__c();
		wf_function.Name = 'Verification';
		wf_function.Workflow_Code__c = wf_def.Id;
		wf_function.Stage__c = function_pre_definition.Id;
		System.runAs(SysUser){
			insert wf_function;
		}
	}
	
	private static void validateLastQueueOwnerNameAndQueueIdAreSync(ID incidentId){
        Case p = [
        	select IOG_Queue_Owner__c, Last_Queue_Owner__c, (select IOG_Queue_Owner__c, Last_Queue_Owner__c from cases)
			from Case 
			where Id =: incidentId];		
		Set<ID> qIDs = new Set<ID>();
		qIDs.add(p.Last_Queue_Owner__c);
		for(Case stub : p.cases){
			qIDs.add(stub.Last_Queue_Owner__c);
		}
		Map<ID, Group> queues = new Map<ID, Group>([select Name from Group where ID IN: qIDs]);
		System.assertEquals((queues.get(p.Last_Queue_Owner__c) == null)? null : queues.get(p.Last_Queue_Owner__c).Name, p.IOG_Queue_Owner__c);
		for(Case stub : p.cases){
			System.assertEquals((queues.get(stub.Last_Queue_Owner__c) == null)? null : queues.get(stub.Last_Queue_Owner__c).Name, stub.IOG_Queue_Owner__c);
		}		
	}
	
	private static void validateCRFCaseLastQueueOwners(ID incidentId, String crfRequestType, String mode){
        Case p = [
        	select Region__c, Last_Queue_Owner__c, IOG_Queue_Owner__c, CSS_CRF_RequestType__c, CRF_Request_Type__c, IR_Priority__c, Status
        	       , (select IOG_Queue_Owner__c from cases order by Product_Family__c asc)
			from Case 
			where Id =: incidentId];
		System.assertEquals(crfRequestType, p.CRF_Request_Type__c);
		if(p.CRF_Request_Type__c.toLowerCase().contains('change request')){
			System.assertEquals('Change Task', p.CSS_CRF_RequestType__c);
			System.assertEquals('Standard', p.IR_Priority__c);
		}else if(p.CRF_Request_Type__c.toLowerCase().contains('inquiry')){
			System.assertEquals('Inquiry', p.CSS_CRF_RequestType__c);
			System.assertEquals('Standard', p.IR_Priority__c);
		}else if(p.CRF_Request_Type__c.toLowerCase().contains('submit document')){
			System.assertEquals('Content Task', p.CSS_CRF_RequestType__c);
			System.assertEquals('Standard', p.IR_Priority__c);
		}else if(p.CRF_Request_Type__c.toLowerCase().contains('escalate')){
			System.assertEquals('Change Task', p.CSS_CRF_RequestType__c);
			System.assertEquals('Escalation', p.IR_Priority__c);
			System.assertEquals('Escalated', p.Status);
		}else{
			System.assertEquals('Change Task', p.CSS_CRF_RequestType__c);
			System.assertEquals('Standard', p.IR_Priority__c);
		}		
		String[] ss = getCRFPackageAndCRFrequestTypeValue(mode, null);
		String ownerString;
		if(p.Region__c == 'In-Region East'){	
			if(p.CSS_CRF_RequestType__c == 'Content Task'){
				System.assertEquals('IOG IR - Receiving Team', p.IOG_Queue_Owner__c);
			}else{
				if(p.Status != 'Escalated'){
					ownerString = ss[3]; // east region & standard
				}else{
					ownerString = ss[4]; // east region & escalated
				}
			}
		}else if(p.Region__c == 'In-Region West'){
			if(p.CSS_CRF_RequestType__c == 'Content Task'){
				System.assertEquals('IOG IR - Receiving Team', p.IOG_Queue_Owner__c);
			}else{
				if(p.Status != 'Escalated'){
					ownerString = ss[5]; // west region & standard
				}else{
					ownerString = ss[6]; // west region & escalated
				}
			}
		}else if(p.Region__c == 'Out-Of-Region'){
			if(p.Status != 'Escalated'){
				ownerString = ss[7]; // oor region & standard
			}else{
				ownerString = ss[8]; // oor region & escalated
			}
		}
		String[] owners = ownerString.split(';');
		System.assertEquals(owners[0], p.IOG_Queue_Owner__c);
		for(Integer i=0; i < p.cases.size() ; i++){
			System.assertEquals(owners[i+1], p.cases[i].IOG_Queue_Owner__c);
		}
	}

	private static void validateSyncParentAndStubCases(ID incidentId, Integer numOfStubs){
        Case p = [
        	select Id, Origin, Region__c, Subject, Description, AccountId, ContactId, IR_Priority__c, CRF_Request_Type__c, CSS_CRF_BusinessName__c, CSS_CRF_ContactNumber__c, CSS_CRF_CustomerContactName__c 
        	          , CSS_CRF_CustomerContactTel__c, CSS_CRF_RVP__c, CSS_CRF_GM__c, Case_CSS_Customer_ID__c, CSS_ProductFamily__c, CSS_CRF_RequestType__c, Total_Case_Count__c 
          	  ,(select Origin, Region__c, Subject, Description, AccountId, ContactId, IR_Priority__c, CRF_Request_Type__c, CSS_CRF_BusinessName__c, CSS_CRF_ContactNumber__c, CSS_CRF_CustomerContactName__c
          	          , CSS_CRF_CustomerContactTel__c, CSS_CRF_RVP__c, CSS_CRF_GM__c, Case_CSS_Customer_ID__c, Product_Family__c from cases order by Product_Family__c asc)
			from Case 
			where Id =: incidentId];
		System.assertEquals(numOfStubs, p.cases.size());
		System.assertEquals(p.cases.size(), p.Total_Case_Count__c);
		if(!p.cases.isEmpty()){
			System.assertNotEquals('Not Defined', p.CSS_CRF_RequestType__c);
		}else{
			System.assertEquals('Not Defined', p.CSS_CRF_RequestType__c);
		}
		Set<String> expectedProductSet = new Set<String>();
		for(Case stub : p.cases){
			expectedProductSet.add(stub.Product_Family__c);
			System.assertEquals(p.Origin, stub.Origin);
			System.assertEquals(p.Region__c, stub.Region__c);
			System.assertEquals(p.Subject, stub.Subject);
			System.assertEquals(p.Description, stub.Description);
			System.assertEquals(p.AccountId, stub.AccountId);
			System.assertEquals(p.ContactId, stub.ContactId);
			System.assertEquals(p.IR_Priority__c, stub.IR_Priority__c);
			System.assertEquals(p.CRF_Request_Type__c, stub.CRF_Request_Type__c);
			System.assertEquals(p.CSS_CRF_RVP__c, stub.CSS_CRF_RVP__c);
			System.assertEquals(p.CSS_CRF_GM__c, stub.CSS_CRF_GM__c);
			System.assertEquals(p.Case_CSS_Customer_ID__c, stub.Case_CSS_Customer_ID__c);
			System.assertEquals(p.CSS_CRF_BusinessName__c, stub.CSS_CRF_BusinessName__c);
			System.assertEquals(p.CSS_CRF_ContactNumber__c, stub.CSS_CRF_ContactNumber__c);
			System.assertEquals(p.CSS_CRF_CustomerContactName__c, stub.CSS_CRF_CustomerContactName__c);
			System.assertEquals(p.CSS_CRF_CustomerContactTel__c, stub.CSS_CRF_CustomerContactTel__c);
		}
		if(numOfStubs > 0){
			List<String> expectedProductList = new List<String>();
			expectedProductList.addAll(expectedProductSet);
			expectedProductList.sort();
			System.assertNotEquals(null, p.CSS_ProductFamily__c);
			List<String> products = p.CSS_ProductFamily__c.split(';');
			products.sort();
			System.assertEquals(expectedProductList.size(), products.size());
			for(Integer i=0; i < products.size(); i++){
				System.assertEquals(expectedProductList[i], products[i]);
			}
		}
	}
	
	private static void validateUnpackThePackageFieldsCorrectly(ID incidentId, String mode){
        Case p = [
        select id, CRF_PACKAGE__c, Fulfillment_Product_Group_Name__c, Feature_Code__c, Feature_Id__c, Item_ID__c, FI_Region_Code__c, Price_Plan_Id__c
                   , Product_Issue__c, Product_code__c, UDAC_Code__c, UDAC_Description__c, RecordType.Name, CSS_CRF_RequestType__c, CSS_ProductFamily__c
          ,(select CRF_PACKAGE__c, Fulfillment_Product_Group_Name__c, Feature_Code__c, Feature_Id__c, Item_ID__c, FI_Region_Code__c, Price_Plan_Id__c
                   , Product_Issue__c, Product_code__c, UDAC_Code__c, UDAC_Description__c, RecordType.Name from cases order by Product_Family__c asc)
		from Case 
		where Id =: incidentId];	
		System.assertEquals('IOG Incident', p.RecordType.Name);
		System.assertEquals(null, p.Fulfillment_Product_Group_Name__c);
		System.assertEquals(null, p.Feature_Code__c);
		System.assertEquals(null, p.Feature_Id__c);
		System.assertEquals(null, p.Item_ID__c);
		System.assertEquals(null, p.FI_Region_Code__c);
		System.assertEquals(null, p.Price_Plan_Id__c);
		System.assertEquals(null, p.Product_Issue__c);
		System.assertEquals(null, p.Product_code__c);
		System.assertEquals(null, p.UDAC_Code__c);
		System.assertEquals(null, p.UDAC_Description__c);
		String[] ss = getCRFPackageAndCRFrequestTypeValue(mode, null);
		for(Case stub : p.cases){
			if(stub.CRF_PACKAGE__c != null){
				String[] cols = stub.CRF_PACKAGE__c.split('<col>');
				validateColumns(cols, stub);						
			}
		}
		if(p.CRF_PACKAGE__c != null){
			String[] rows = p.CRF_PACKAGE__c.split('<row>');
			System.assert(p.cases.size() >= rows.size());
			for(String r : rows){
				if(r != null){
					String[] cols = r.split('<col>');
					Boolean isPass = false;
					for(Case stub : p.cases){
						if(cols[9] == stub.UDAC_Code__c){
							if(cols[0] == stub.RecordType.Name || (('IOG ' + p.CSS_CRF_RequestType__c) == stub.RecordType.Name)){
								validateColumns(cols, stub);
								isPass = true;
								break;								
							}
						}
					}
					System.assert(isPass);
				}
			}
		}		
	}
	
	private static void validateColumns(String[] cols, Case c){
		System.assertEquals(cols[1], c.Fulfillment_Product_Group_Name__c);
		System.assertEquals(cols[2], c.Feature_Code__c);
		System.assertEquals(cols[3] == ''? null : Integer.valueOf(cols[3]), c.Feature_Id__c);
		System.assertEquals(cols[4] == ''? null : Integer.valueOf(cols[4]), c.Item_ID__c);
		System.assertEquals(cols[5], c.FI_Region_Code__c);
		System.assertEquals(cols[6] == ''? null : Integer.valueOf(cols[6]), c.Price_Plan_Id__c);
		System.assertEquals(cols[7], c.Product_Issue__c);
		System.assertEquals(cols[8], c.Product_code__c);
		System.assertEquals(cols[9], c.UDAC_Code__c);
		System.assertEquals(cols[10].trim(), c.UDAC_Description__c.trim());			
	}

	private static void validateAfterInitiateChange(ID csId){
		Case cs = [select Status, Fulfillment_Item_Owner__c, Fulfillment_Item_Status__c, Fulfillment_Item_Task__c, Fulfillment_Product_Group__c, Fulfillment_Item__c
		           ,  Fulfillment_Item__r.Owner.Name, Fulfillment_Item__r.Status__c, Fulfillment_Item__r.Current_Step__c, Fulfillment_Item__r.Fulfillment_Product_Group__c
		           from Case where Id =: csId];
		System.assertEquals('In Workflow', cs.Status);           
		System.assertNotEquals(null, cs.Fulfillment_Item__c);
		System.assertEquals(cs.Fulfillment_Item__r.Owner.Name, cs.Fulfillment_Item_Owner__c);
		System.assertEquals(cs.Fulfillment_Item__r.Status__c, cs.Fulfillment_Item_Status__c);
		System.assertEquals(cs.Fulfillment_Item__r.Current_Step__c, cs.Fulfillment_Item_Task__c);
		System.assertEquals(cs.Fulfillment_Item__r.Fulfillment_Product_Group__c, cs.Fulfillment_Product_Group__c);
	}
			
	static testMethod void testCRFOriginCasesInCRFMode() {
		initialize();
		Case p = createNewIncidentCaseWithPackageFields('CRF', CRFMODE, 'Inquiry - Product Status', EastUser, EASTAcctId, EASTContactId);
		validateSyncParentAndStubCases(p.Id, 5);    
		validateUnpackThePackageFieldsCorrectly(p.Id, CRFMODE);		
		validateLastQueueOwnerNameAndQueueIdAreSync(p.Id);		
	}

	static testMethod void testCasesInAccountMode() {
		initialize();
		Case p = createNewIncidentCaseWithPackageFields('CRF', ACCOUNTMODE, 'Submit Document – Domain Form', EastUser, EASTAcctId, EASTContactId);
		validateSyncParentAndStubCases(p.Id, 5);    
		validateUnpackThePackageFieldsCorrectly(p.Id, ACCOUNTMODE);		
		validateLastQueueOwnerNameAndQueueIdAreSync(p.Id);		
	}
					
	static testMethod void testEmailOriginCasesInIncidentMode() {
		initialize();
		Case p = createNewIncidentCaseOnlyNoPackageFields('Email', EastUser, EASTAcctId, EASTContactId);
		validateSyncParentAndStubCases(p.Id, 0);
		String[] ss = getCRFPackageAndCRFrequestTypeValue(INCIDENTMODE, null);
		p.CRF_PACKAGE__c = ss[0];
		p.CRF_Request_Type__c = null;
		System.runAs(EastUser){
			update p;
		}
		validateSyncParentAndStubCases(p.Id, 5);
		validateUnpackThePackageFieldsCorrectly(p.Id, INCIDENTMODE);	
		validateLastQueueOwnerNameAndQueueIdAreSync(p.Id);
	}
	
	static testMethod void testStubCasesInStubMode() {
		initialize();
		Case p = createNewIncidentCaseOnlyNoPackageFields('Phone', EastUser, EASTAcctId, EASTContactId);
		Case s = createNewStubCaseManually(p, EastUser, IOGContentTask_CASE_RecordType, 'YP SEO');
		validateSyncParentAndStubCases(p.Id, 1);
		String[] ss1 = getCRFPackageAndCRFrequestTypeValue(STUBMODE, null);
		s.CRF_PACKAGE__c = ss1[0];
		System.runAs(EastUser){
			update s;
		}
		validateSyncParentAndStubCases(p.Id, 1);
		validateUnpackThePackageFieldsCorrectly(p.Id, STUBMODE);
		String[] ss2 = getCRFPackageAndCRFrequestTypeValue(INCIDENTMODE, null);
		p.CRF_PACKAGE__c = ss2[0];
		p.CRF_Request_Type__c = null;
		System.runAs(EastUser){
			update p;
		}
		validateSyncParentAndStubCases(p.Id, 6);
		validateUnpackThePackageFieldsCorrectly(p.Id, INCIDENTMODE);
		validateLastQueueOwnerNameAndQueueIdAreSync(p.Id);			
	}
	
	static testMethod void testCRFCasesAssignmentRules() {
		initialize();
		Case p = createNewIncidentCaseWithPackageFields('CRF', CRFMODE, 'Change Request – Other', EastUser, EASTAcctId, EASTContactId);
		validateCRFCaseLastQueueOwners(p.Id, 'Change Request – Other', CRFMODE);	
		validateLastQueueOwnerNameAndQueueIdAreSync(p.Id);
	}

	static testMethod void testCRFCasesAssignmentRulesWESTRegion_standard() {
		initialize();
		Case p_standard = createNewIncidentCaseWithPackageFields('CRF', CRFMODE_WEST, 'Change Request – Other', WestUser, WESTAcctId, WESTContactId);
		validateCRFCaseLastQueueOwners(p_standard.Id, 'Change Request – Other', CRFMODE_WEST);	
		validateLastQueueOwnerNameAndQueueIdAreSync(p_standard.Id);
	}

	static testMethod void testCRFCasesAssignmentRulesWESTRegion_escalate() {
		initialize();
		Case p_escalate = createNewIncidentCaseWithPackageFields('CRF', CRFMODE_WEST, 'Escalate – Other', WestUser, WESTAcctId, WESTContactId);
		validateCRFCaseLastQueueOwners(p_escalate.Id, 'Escalate – Other', CRFMODE_WEST);	
	}
			
	static testMethod void testAppendIOGEmailFooter() {
		initialize();
		Case p = createNewIncidentCaseOnlyNoPackageFields('Phone', EastUser, EASTAcctId, EASTContactId);
		Case queried = [select CaseNumber, CSS_CustomerID__c, RecordTypeId, OwnerId, Owner.Name from Case where ID =: p.Id];
		String appended = CaseIOGClass.appendFooterToIOGEmails(queried, WestUser.Id, '[ATTi Case Number: 01554519 / Case Owner: ss1112 / Sent By: ss1112 / CSS Customer ID: ]');
		String expected = '[ATTi Case Number: ' + queried.CaseNumber + ' / Case Owner: ' + EastUser.ATTUID__c + ' / Sent By: ' + WestUser.ATTUID__c + ' / CSS Customer ID: ' + queried.CSS_CustomerID__c + ']';
		System.assertEquals(expected, appended);
	}
	
	static testMethod void testInitiateChanges() {
		initialize();
		Case p = createNewIncidentCaseWithPackageFields('CRF', CRFMODE, 'Change Request – Other', EastUser, EASTAcctId, EASTContactId);
		Case changetaskStub = [select Id, Region__c, Fulfillment_Product_Group_Name__c, UDAC_Code__c from Case where ParentId =: p.Id limit 1];
		//addNewFulfillmentItemRecordsForInitiateChange(changetaskStub);
		changetaskStub.AFrontier_Issue__c = 'Billing Inquiries';
		changetaskStub.AFrontier_Reason__c = 'Auto-Reply';
		System.runAs(EastUser){
			CaseIOGInitiateChange.CreateFulfillmentItems(changetaskStub.Id);
		}
		//validateAfterInitiateChange(changetaskStub.Id);
	}

	static testMethod void testInitiateChangesWebServiceCall() {
		initialize();
		Case p = createNewIncidentCaseWithPackageFields('CRF', CRFMODE, 'Change Request – Other', EastUser, EASTAcctId, EASTContactId);
		Case changetaskStub = [select Id, Region__c, Fulfillment_Product_Group_Name__c, UDAC_Code__c from Case where ParentId =: p.Id limit 1];
		FulfillmentWebService.BasicHttpBinding_IFulFillmentService delegate = new FulfillmentWebService.BasicHttpBinding_IFulFillmentService();
		delegate.UpsertFulfillmentMapping(changetaskStub.Id,'0123456789','productCode','productIssue','itemId','priceplanId','featureId','In-Region East');
	}	      	
}